home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / util / gifmachn / part01 next >
Internet Message Format  |  1990-09-03  |  60KB

  1. Path: abcfd20.larc.nasa.gov!amiga-request
  2. From: amiga-request@abcfd20.larc.nasa.gov (Amiga Sources/Binaries Moderator)
  3. Subject: v90i245: GIFMachine 1.0 - convert GIF pictures into IFF SHAM, Part01/02
  4. Reply-To: caw@miroc.Chi.IL.US (Christopher A. Wichura)
  5. Newsgroups: comp.sources.amiga
  6. Message-ID: <comp.sources.amiga:v90i245@abcfd20.larc.nasa.gov>
  7. Date: 03 Sep 90 22:37:08 GMT
  8. Approved: tadguy@uunet.UU.NET (Tad Guy)
  9. X-Mail-Submissions-To: amiga@uunet.uu.net
  10. X-Post-Discussions-To: comp.sys.amiga
  11.  
  12. Submitted-by: caw@miroc.Chi.IL.US (Christopher A. Wichura)
  13. Posting-number: Volume 90, Issue 245
  14. Archive-name: util/gifmachine-1.0/part01
  15.  
  16. [ uuencoded executable enclosed  ...tad ]
  17.  
  18. GIFMachine will convert GIF pictures into IFF SHAM format (and __ONLY__
  19. SHAM).  I wrote it as a replacement for ShamSharp, which I feel has a
  20. number of problems:  GURU's in SHAM more on GIFs with greater than 400
  21. lines, does not fully conform to the GIF spec, always drops the odd pixels
  22. out on images wider than 320 pixels, writes bad IFFs on a regular basis,
  23. etc.  GIFMachine has none of these problems, and tends to get less for the
  24. colour error as well.
  25.  
  26. GIFMachine requires the arp library, v39 or greater, to be present.  It
  27. runs just dandy on my 3000, too! :-)  On a stock 500/1000/2000 it takes
  28. around a half hour to convert an image around 640x480 (as opposed to 2 and
  29. a half minutes on the 3000).  GIFMachine has been tested with images as
  30. large as 1152x890.
  31.  
  32. Please note that unless you have the viewer `Mostra', by S. Vigna, images with
  33. >400 lines can not be properly viewed after conversion.  This is because
  34. the other SHAM viewers either 1) Assume nothing greater than 400 exists and
  35. will not allow scrolling around, or 2) allow scrolling, but don't rebuild
  36. the copper list when scrolling vertically so as soon as you scroll down the
  37. image gets scragged.
  38.  
  39. Lattice C 5.05 source code has been provided in this archive, as well as an
  40. lmkfile to build it.  Manx users will probably have to play around with the
  41. custom startup code I use, but the rest ought to work more or less
  42. straight.  Note that I have my ARP glue routines in the file LIB:ARP
  43. instead of in the arpglue.o file that is distributed with the ARP 1.3
  44. programmers' kit.
  45.  
  46. -=> CAW
  47.  
  48. #!/bin/sh
  49. # This is a shell archive.  Remove anything before this line, then unpack
  50. # it by saving it into a file and typing "sh file".  To overwrite existing
  51. # files, type "sh file -c".  You can also feed this as standard input via
  52. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  53. # will see the following message at the end:
  54. #        "End of archive 1 (of 2)."
  55. # Contents:  GIFMachine.docs GIFMachine.h colourlist.c doimage.c
  56. #   extensions.c giftosham.c lmkfile main.c rgbdiff.c startup.a
  57. #   stripborder.c warncli.c writeiff.c xcomp.c
  58. # Wrapped by tadguy@abcfd20 on Mon Sep  3 18:37:04 1990
  59. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  60. if test -f 'GIFMachine.docs' -a "${1}" != "-c" ; then 
  61.   echo shar: Will not clobber existing file \"'GIFMachine.docs'\"
  62. else
  63. echo shar: Extracting \"'GIFMachine.docs'\" \(6277 characters\)
  64. sed "s/^X//" >'GIFMachine.docs' <<'END_OF_FILE'
  65. X
  66. X                                GIFMachine
  67. X
  68. X                 Copyright 1990 by Christopher A. Wichura
  69. X                           (caw@miroc.chi.il.us)
  70. X
  71. X
  72. XLegal mumbo jumbo:
  73. X
  74. XGIFMachine is not in the public domain.  All source files, along with the
  75. Xresulting executable, are copyright by C. Wichura.  You may not sell
  76. XGIFMachine.  The only allowed charge that may be placed on GIFMachine is
  77. Xfor media and/or mailing costs.
  78. X
  79. XGIFMachine may be freely redistributed via BBSs, InterNet/Usenet, and disk
  80. Xlibraries such as Fred Fish's, as long as the archive is not modified.
  81. XDisk magazines and services that charge for file transfers may not
  82. Xdistribute GIFMachine.
  83. X
  84. XIn using GIFMachine, you accept the responsibility for any damage or loss of
  85. Xproductivity/money that may occur through or during its use.  C. Wichura is
  86. Xnot and can not be held accountable.
  87. X
  88. X                            What is GIFMachine?
  89. X                            ~~~~~~~~~~~~~~~~~~~
  90. XGIFMachine is a program that converts pictures stored in the CompuServe GIF
  91. X(Graphics Interchange Format) format into IFF SHAM format.  There are very
  92. Xfew programs that do this, and most have many problems (not that GIFMachine
  93. Xdoesn't either -- see below).
  94. X
  95. XFor a long time, I used a program called ShamSharp to convert GIFs to IFF
  96. Xformat.  ShamSharp was the only thing I would even consider using (execpt
  97. Xfor ASDG's The Art Department, a very fine commercial product!).  However,
  98. Xthere were a number of things about it that irked me.
  99. X
  100. X   1)  If a picture had >16 colours and a width >320, ShamSharp would
  101. X       __ALWAYS__ halve the width of the image.  Not only that, but it
  102. X       did so by simply skipping every other pixel of the original GIF.
  103. X       This resulted in a tremendous loss in resolution.
  104. X       
  105. X       I, myself, would rather have the entire picture converted and be
  106. X       able to use my favorite viewer (Mostra, by S. Vigna) to scroll
  107. X       around the image.  Thus, by default, GIFMachine will not halve
  108. X       the picture's width.  There is a command line switch to make it
  109. X       do so, however, in which case it actually thinks about it a bit
  110. X       rather than just dropping the odd pixels.
  111. X
  112. X   2)  If an image had more than 400 lines in it, ShamSharp would
  113. X       GURU the system if the SHAM mode flag was used.  GIFMachine handles
  114. X       large pictures well (that was one of the primary concerns I had
  115. X       while writing it) and has been tested with images as large as
  116. X       1152x890!
  117. X
  118. X   3)  ShamSharp would write bad IFF files for me on a regular basis.  I
  119. X       suspect this is because of some subtle bug in the cmpByteRun1
  120. X       compression routine ShamSharp uses.  Anyway, GIFMachine has yet to
  121. X       write a bad IFF on me.  (Cross Fingers, Cross Fingers :-)
  122. X
  123. XGIFMachine also offers the user the ability to automatically remove a
  124. Xborder area in a picture.  (I just hate it when you have an image floating
  125. Xin the middle of the screen with inches of nothing around it.)
  126. X
  127. XYou can also use full ARP wildcards and multiple file specs, much as with
  128. Xthe ARP C:MOVE command.  This eases conversion of a large number of images.
  129. X
  130. X                          Drawbacks of GIFMachine
  131. X                          ~~~~~~~~~~~~~~~~~~~~~~~
  132. XIf you are looking for speed, go someplace else.  GIFMachine was written
  133. Xwith the idea of getting the best possible image from a GIF file, not as
  134. Xsomething to view GIFs in a quick and dirty manner.  Usually what I do is
  135. Xuse something like HAMGIF to see if the GIF is actually worth the effort
  136. Xand then convert a series of GIFs in one shot by specifying multiple
  137. Xfilepspecs.  On a stock 500, the average picture takes around 25 minutes to
  138. Xconvert (half that if the image is interlaced, which is often the case when
  139. Xthe width is halved).
  140. X
  141. XGIFMachine knows how to write only one thing: SHAMs.  If a picture only
  142. Xuses <= 16 colours, SHAM is not needed.  It would be much faster to write a
  143. Xnormal IFF and skip the SHAM conversion calculations.  In such a case, it
  144. Xwould be better to go back and use something like ShamSharp.
  145. X
  146. XThe only viewer I know of that properly handles SHAMs with >400 lines is
  147. XMostra.  SuperSham 3.2 (?) will display the image, but does not allow
  148. Xscrolling around.  The latest version of Christian Weber's ShowIFF
  149. X(included in the v18.? distribution of his iff.library) will also display
  150. XSHAMs and let one scroll around.  However, he does not rebuild the copper
  151. Xlist during vertical scrolling and thus the image turns to muck if one
  152. Xscrolls down.
  153. X
  154. X                             Using GIFMachine
  155. X                             ~~~~~~~~~~~~~~~~
  156. XGIFMachine requires that you have the arp.library, version 39 or greater,
  157. Xin your LIBS: directory.  It also requires a fair amount of RAM (though it
  158. Xdoes not have to be CHIP RAM or contiguous).  The 1152x890 image required
  159. X1.9 megs of memory to convert.
  160. X
  161. XGIFMachine uses the arp GADS() argument parser.  Thus, one can always enter
  162. X`GIFMachine ?' on the command line for help.  GIFMachine can not be run
  163. Xfrom the WorkBench.
  164. X
  165. XGIFMachine accepts the following arguments:
  166. X
  167. X<filespec1> ... <filespecN> [TO <directory or filespec>] [ALL]
  168. X                            [NOBORDER <line thresh>] [XCOMP]
  169. X
  170. XEach filespec may contain any valid ARP wildcards (really regular
  171. Xexpressions).
  172. X
  173. XThe TO option allows one to specify where to put the IFFs.  If not given,
  174. Xthey will be placed in the current directory.  It is generally advised that
  175. XTO point at a directory.  However, if you are converting only a single GIF
  176. Xfile then there is not reason one can not specify a full filespec.
  177. X
  178. XThe ALL option will cause GIFMachine to recursively descend into any
  179. Xdirectories while matching filespecs.
  180. X
  181. XThe NOBORDER option instructs GIFMachine to remove the border area from an
  182. Ximage.  It takes, as its <line thresh> parameter, an integer between 0 and
  183. X100 that indicates what percentage of a line can differ from the border
  184. Xcolour and still have the line removed.
  185. X
  186. XThe final option, XCOMP, tells GIFMachine to halve the width of images with
  187. Xa width >320.
  188. X
  189. XNote that if GIFMachine determines that the image can be written interlaced
  190. X(depends on aspect ratios) then it will work on two lines at a time instead
  191. Xof one.  This is because the SHAM format only changes the base colours
  192. Xevery other line when displaying interlaced images.
  193. X
  194. X-=> CAW
  195. END_OF_FILE
  196. if test 6277 -ne `wc -c <'GIFMachine.docs'`; then
  197.     echo shar: \"'GIFMachine.docs'\" unpacked with wrong size!
  198. fi
  199. # end of 'GIFMachine.docs'
  200. fi
  201. if test -f 'GIFMachine.h' -a "${1}" != "-c" ; then 
  202.   echo shar: Will not clobber existing file \"'GIFMachine.h'\"
  203. else
  204. echo shar: Extracting \"'GIFMachine.h'\" \(2628 characters\)
  205. sed "s/^X//" >'GIFMachine.h' <<'END_OF_FILE'
  206. X/* Copyright 1990 by Christopher A. Wichura.
  207. X   See file GIFMachine.doc for full description of rights.
  208. X*/
  209. X
  210. X#include <exec/types.h>
  211. X#define DO_ARP_COPIES
  212. X#include <libraries/ArpBase.h>
  213. X#include <proto/exec.h>
  214. X#include <string.h>
  215. X
  216. X/* reference ArpBase so that the #pragma's won't choke */
  217. Xextern struct ArpBase *ArpBase;
  218. X
  219. X/* some structures to make parsing the gif files a bit easier */
  220. Xstruct GIFdescriptor {
  221. X    UWORD gd_Width;
  222. X    UWORD gd_Height;
  223. X    UBYTE gd_ColInfo;
  224. X    UBYTE gd_BackGround;
  225. X    UBYTE gd_Reserved;
  226. X};
  227. X
  228. Xstruct ImageDesc {
  229. X    UWORD id_Left;
  230. X    UWORD id_Top;
  231. X    UWORD id_Width;
  232. X    UWORD id_Height;
  233. X    UBYTE id_Info;
  234. X};
  235. X
  236. X#define GIF_IMAGE      0x2C
  237. X#define GIF_EXTENSION  0x21
  238. X#define GIF_TERMINATOR 0x3B
  239. X
  240. X/* this magic cookie defines the maximum size of the master colour list */
  241. X#define MAXCOLOURS 4096
  242. X
  243. X/* convert a GIF colour intensity into an Amiga intensity */
  244. X#define CVRTGIF(a) buf[a] >> 4
  245. X
  246. X/* these next macros are used to get the r, g, and b values of a given
  247. X   index */
  248. X#define GetRed(a)    (UBYTE)(MasterColourTable[a] >> 8)
  249. X#define GetGreen(a)    (UBYTE)((MasterColourTable[a] >> 4) & 0xF)
  250. X#define GetBlue(a)    (UBYTE)(MasterColourTable[a] & 0xF)
  251. X
  252. X/* determine if pic is too wide to be entirely on a HAM screen */
  253. X#define ISTOOBIG (gdesc.gd_Width > 320)
  254. X
  255. X/* whenever we want to abort we will return this as our error code */
  256. X#define ABORTEXITVAL 1
  257. X
  258. X/* function prototypes we use */
  259. Xextern int __regargs main(char *cmdptr, int cmdlen, struct WBStartup *WBMsg);
  260. Xextern void    XCEXIT(int);
  261. Xextern void    WarnMustUseCLI(void);
  262. Xextern void    DoPattern(char *);
  263. Xextern void    Convert(char *);
  264. Xextern BOOL    IsDir(char *);
  265. Xextern void    FlipWord(UWORD *);
  266. Xextern BOOL    DoImage(BPTR);
  267. Xextern BOOL    DoExtension(BPTR);
  268. Xextern UWORD    AddColour(UBYTE *);
  269. Xextern BOOL    WriteIFF(char *);
  270. Xextern void    PutValue(UWORD, UWORD, UWORD);
  271. Xextern UWORD    GetValue(UWORD, UWORD);
  272. Xextern int    ReadCode(BPTR);
  273. Xextern void    AddPixel(UBYTE);
  274. Xextern void    StripBorder(void);
  275. Xextern BOOL    BorderCheck(UWORD, UWORD);
  276. Xextern void    DoXComp(void);
  277. Xextern void    GIFtoSHAM(void);
  278. Xextern void    GetPalette(ULONG, ULONG);
  279. Xextern void    InitDiff(void);
  280. Xextern ULONG    RGBdiff(UBYTE, UBYTE, UBYTE, UBYTE, UBYTE, UBYTE);
  281. Xextern void    OutDump(int);
  282. Xextern void    OutRun(int, int);
  283. Xextern BOOL    PutLong(ULONG);
  284. Xextern BOOL    PutWord(UWORD);
  285. Xextern BOOL    PutChar(UBYTE);
  286. X
  287. X/* modules that want to use the Get/PutValue macros should include this
  288. X   next macro to externally reference the picture storage array */
  289. X#define EXTERNBITPLANE extern UWORD **BitPlane
  290. X
  291. X/* these two macros get and store values in the picture plane */
  292. X#define GetValue(a, b)    BitPlane[b][a]
  293. X#define PutValue(a, b, c) BitPlane[b][a] = c
  294. END_OF_FILE
  295. if test 2628 -ne `wc -c <'GIFMachine.h'`; then
  296.     echo shar: \"'GIFMachine.h'\" unpacked with wrong size!
  297. fi
  298. # end of 'GIFMachine.h'
  299. fi
  300. if test -f 'colourlist.c' -a "${1}" != "-c" ; then 
  301.   echo shar: Will not clobber existing file \"'colourlist.c'\"
  302. else
  303. echo shar: Extracting \"'colourlist.c'\" \(788 characters\)
  304. sed "s/^X//" >'colourlist.c' <<'END_OF_FILE'
  305. X/* Copyright 1990 by Christopher A. Wichura.
  306. X   See file GIFMachine.doc for full description of rights.
  307. X*/
  308. X
  309. X#include "GIFMachine.h"
  310. X
  311. XUWORD TotalColours;
  312. XUWORD MasterColourTable[MAXCOLOURS];
  313. X
  314. XUWORD AddColour(UBYTE *buf)
  315. X{
  316. X    register UWORD colour;
  317. X    register UWORD index;
  318. X
  319. X    colour = (UWORD)(CVRTGIF(0) << 8 | CVRTGIF(1) << 4 | CVRTGIF(2));
  320. X
  321. X    for (index = 0; index < TotalColours; index++) {
  322. X        if (colour == MasterColourTable[index])
  323. X            return index;
  324. X    }
  325. X
  326. X    /* note that we don't check to see if the list is full.  this is
  327. X       because we can't possibly have more than max colours because
  328. X       16 * 16 * 16 is MAXCOLOURS and thus we will match somewhere in
  329. X       the table when it is full.  Not to hot of en explanation, eh? */
  330. X
  331. X    MasterColourTable[TotalColours] = colour;
  332. X    return TotalColours++;    
  333. X}
  334. END_OF_FILE
  335. if test 788 -ne `wc -c <'colourlist.c'`; then
  336.     echo shar: \"'colourlist.c'\" unpacked with wrong size!
  337. fi
  338. # end of 'colourlist.c'
  339. fi
  340. if test -f 'doimage.c' -a "${1}" != "-c" ; then 
  341.   echo shar: Will not clobber existing file \"'doimage.c'\"
  342. else
  343. echo shar: Extracting \"'doimage.c'\" \(5222 characters\)
  344. sed "s/^X//" >'doimage.c' <<'END_OF_FILE'
  345. X/* Copyright 1990 by Christopher A. Wichura.
  346. X   See file GIFMachine.doc for full description of rights.
  347. X*/
  348. X
  349. X#include "GIFMachine.h"
  350. X
  351. Xextern struct GIFdescriptor gdesc;
  352. XEXTERNBITPLANE;
  353. X
  354. Xstatic struct ImageDesc idesc;
  355. Xextern UWORD GlobalColourTable[256];
  356. Xstatic UWORD LocalColourTable[256];
  357. Xextern ULONG ImageNumber;
  358. X
  359. Xextern char *AbortMsg;
  360. X
  361. Xstatic UWORD Xpos, Ypos;
  362. Xstatic BOOL interleave;
  363. X
  364. Xstatic UBYTE LeaveStep[5]  = {1, 8, 8, 4, 2};
  365. Xstatic UBYTE LeaveFirst[5] = {0, 0, 4, 2, 1};
  366. X
  367. X/* some variables used by the decompressor */
  368. Xstatic int ReadError;
  369. Xstatic UBYTE CodeSize;
  370. Xstatic int EOFCode;
  371. Xstatic UBYTE ReadMask;
  372. Xstatic int CompDataPointer;
  373. Xstatic int CompDataCount;
  374. Xstatic UBYTE CompData[256];
  375. X
  376. X/* tables used by the decompressor */
  377. Xstatic UWORD Prefix[4096];
  378. Xstatic UBYTE Suffix[4096];
  379. Xstatic UBYTE OutCode[1025];
  380. X
  381. XBOOL DoImage(BPTR fh)
  382. X{
  383. X    UBYTE buf[3];
  384. X    register int index;
  385. X    register int colours;
  386. X
  387. X    Printf("...Image #%ld encountered.\n", ImageNumber++);
  388. X
  389. X    if (Read(fh, (char *)&idesc, 9) != 9) {
  390. X        Puts("......Error reading image descriptor.");
  391. X        return TRUE;
  392. X    }
  393. X
  394. X    FlipWord(&idesc.id_Left);
  395. X    FlipWord(&idesc.id_Top);
  396. X    FlipWord(&idesc.id_Width);
  397. X    FlipWord(&idesc.id_Height);
  398. X
  399. X    interleave = idesc.id_Info & 1L << 6;
  400. X    if (interleave)
  401. X        interleave = 1;
  402. X
  403. X    Printf("......Xpos from %ld to %ld, Ypos from %ld to %ld, %sinterlaced.\n",
  404. X        idesc.id_Left, idesc.id_Left + idesc.id_Width - 1,
  405. X        idesc.id_Top, idesc.id_Top + idesc.id_Height - 1,
  406. X        interleave ? "" : "not ");
  407. X
  408. X    if (idesc.id_Info & 1L << 7) {
  409. X        colours = 1L << ((idesc.id_Info & 7) + 1);
  410. X        Printf("......Local colour map contains %ld entries.\n", colours);
  411. X
  412. X        for (index = 0; index < colours; index++) {
  413. X            if (Read(fh, buf, 3) != 3) {
  414. X                Printf("......Error reading local colour #%ld.\n",
  415. X                    index);
  416. X                return TRUE;
  417. X            }
  418. X
  419. X            LocalColourTable[index] = AddColour(buf);
  420. X        }
  421. X    } else {
  422. X        colours = 1L << ((gdesc.gd_ColInfo & 7) + 1);
  423. X        CopyMem((char *)GlobalColourTable, (char *)LocalColourTable,
  424. X            sizeof(LocalColourTable));
  425. X    }
  426. X
  427. X    Xpos = Ypos = 0;
  428. X
  429. X    /* now we are ready to read the image in so do it! */
  430. X
  431. X    {
  432. X        int Code, MaxCode, ClearCode, CurCode,
  433. X            OldCode, InCode, FreeCode;
  434. X        int OutCount;
  435. X        int FirstFree;
  436. X        UBYTE InitCodeSize, FinChar, BitMask;
  437. X
  438. X        Printf("......Decompressing line number %5ld", Ypos);
  439. X
  440. X        /* get the codesize and do general setup for decompression */
  441. X        if (Read(fh, buf, 1) != 1) {
  442. X            Puts("\n......I/O Error during decompression.");
  443. X            return TRUE;
  444. X        }
  445. X
  446. X        CodeSize = buf[0];
  447. X        ClearCode = 1L << CodeSize;
  448. X        EOFCode = ClearCode + 1;
  449. X        FreeCode = FirstFree = ClearCode + 2;
  450. X
  451. X        CodeSize++;    /* per GIF spec */
  452. X        InitCodeSize = CodeSize;
  453. X        MaxCode = 1L << CodeSize;
  454. X        ReadError = ReadMask = OutCount = 0;
  455. X        CompDataPointer = CompDataCount = 0;
  456. X
  457. X        BitMask = colours - 1;
  458. X
  459. X        Code = ReadCode(fh);
  460. X        while (Code != EOFCode) {
  461. X            if (ReadError)
  462. X                return TRUE;
  463. X
  464. X            if (CheckAbort(NULL)) {
  465. X                Printf("\n%s\n", AbortMsg);
  466. X                XCEXIT(ABORTEXITVAL);
  467. X            }
  468. X
  469. X            if (Code == ClearCode) {
  470. X                CodeSize = InitCodeSize;
  471. X                MaxCode = 1L << CodeSize;
  472. X                FreeCode = FirstFree;
  473. X                FinChar = CurCode = OldCode = Code = ReadCode(fh);
  474. X                AddPixel(FinChar);
  475. X            } else {
  476. X                CurCode = InCode = Code;
  477. X
  478. X                if (CurCode >= FreeCode) {
  479. X                    CurCode = OldCode;
  480. X                    OutCode[OutCount++] = FinChar;
  481. X                }
  482. X
  483. X                while (CurCode > BitMask) {
  484. X                    if (OutCount > 1024) {
  485. X                        Puts("\n......Corrupt GIF file (OutCount)");
  486. X                        return TRUE;
  487. X                    }
  488. X
  489. X                    OutCode[OutCount++] = Suffix[CurCode];
  490. X                    CurCode = Prefix[CurCode];
  491. X                }
  492. X
  493. X                FinChar = CurCode;
  494. X                AddPixel(FinChar);
  495. X
  496. X                for (index = OutCount - 1; index >= 0; index--)
  497. X                    AddPixel(OutCode[index]);
  498. X                OutCount = 0;
  499. X
  500. X                Prefix[FreeCode] = OldCode;
  501. X                Suffix[FreeCode] = FinChar;
  502. X                OldCode = InCode;
  503. X
  504. X                if (++FreeCode >= MaxCode) {
  505. X                    if (CodeSize < 12) {
  506. X                        CodeSize++;
  507. X                        MaxCode <<= 1;
  508. X                    }
  509. X                }
  510. X            }
  511. X
  512. X            Code = ReadCode(fh);
  513. X        }
  514. X    }
  515. X
  516. X    if (Read(fh, buf, 1) != 1) {
  517. X        return TRUE;
  518. X    }
  519. X
  520. X    /* done decompressing.  Erase decompressing message and exit */
  521. X    Puts("\x9B" "22D\x9BKed.");
  522. X
  523. X    if (buf[0] != 0)
  524. X        Puts("......Warning:  Unaligned packet.");
  525. X
  526. X    return FALSE;
  527. X}
  528. X
  529. Xstatic UBYTE ByteBuf;
  530. X
  531. Xint ReadCode(BPTR fh)
  532. X{
  533. X    register int temp;
  534. X    register int DstMasked;
  535. X    register int DstMask;
  536. X    UBYTE buf[1];
  537. X
  538. X    temp = 0;
  539. X    DstMasked = 1L << CodeSize;
  540. X    for (DstMask = 1; DstMask != DstMasked; DstMask <<= 1) {
  541. X        if (!ReadMask) {
  542. X            if (CompDataPointer == CompDataCount) {
  543. X                if (Read(fh, (char *)buf, 1) != 1) {
  544. X                    Puts("\n......I/O Error during decompression.");
  545. X                    ReadError = 1;
  546. X                    return EOFCode;
  547. X                }
  548. X
  549. X                if (Read(fh, (char *)CompData, buf[0]) != buf[0]) {
  550. X                    Puts("\n......I/O Error during decompression.");
  551. X                    ReadError = 1;
  552. X                    return EOFCode;
  553. X                }
  554. X
  555. X                CompDataCount = buf[0];
  556. X                CompDataPointer = 0;
  557. X            }
  558. X
  559. X            ReadMask = 1;
  560. X            ByteBuf = CompData[CompDataPointer++];
  561. X        }
  562. X
  563. X        if (ByteBuf & ReadMask)
  564. X            temp |= DstMask;
  565. X
  566. X        ReadMask <<= 1;
  567. X    }
  568. X
  569. X    return temp;
  570. X}
  571. X
  572. Xvoid AddPixel(UBYTE index)
  573. X{
  574. X    PutValue((UWORD)(Xpos + idesc.id_Left), (UWORD)(Ypos + idesc.id_Top),
  575. X        LocalColourTable[index]);
  576. X
  577. X    if (++Xpos == idesc.id_Width) {
  578. X        Xpos = 0;
  579. X        Ypos += LeaveStep[interleave];
  580. X        if (Ypos >= idesc.id_Height)
  581. X            Ypos = LeaveFirst[++interleave];
  582. X
  583. X        Printf("\x9B" "5D%5ld", Ypos + idesc.id_Top);
  584. X    }
  585. X}
  586. END_OF_FILE
  587. if test 5222 -ne `wc -c <'doimage.c'`; then
  588.     echo shar: \"'doimage.c'\" unpacked with wrong size!
  589. fi
  590. # end of 'doimage.c'
  591. fi
  592. if test -f 'extensions.c' -a "${1}" != "-c" ; then 
  593.   echo shar: Will not clobber existing file \"'extensions.c'\"
  594. else
  595. echo shar: Extracting \"'extensions.c'\" \(755 characters\)
  596. sed "s/^X//" >'extensions.c' <<'END_OF_FILE'
  597. X/* Copyright 1990 by Christopher A. Wichura.
  598. X   See file GIFMachine.doc for full description of rights.
  599. X*/
  600. X
  601. X#include "GIFMachine.h"
  602. X
  603. Xstatic UBYTE buf[256];
  604. X
  605. XBOOL DoExtension(BPTR fh)
  606. X{
  607. X    register int size;
  608. X
  609. X    if (Read(fh, buf, 1) != 1) {
  610. X        Puts("...Error reading extension block function code.");
  611. X        return TRUE;
  612. X    }
  613. X
  614. X    Printf("...Extension block function code #%ld not know, skipping.\n",
  615. X         buf[0]);
  616. X
  617. X    /* we must skip over any data for the extension block */
  618. X    for (;;) {
  619. X        if (Read(fh, buf, 1) != 1) {
  620. X            Puts("...Error reading extension block function code.");
  621. X            return TRUE;
  622. X        }
  623. X
  624. X        size = buf[0];
  625. X
  626. X        if (size == 0)
  627. X            return FALSE;
  628. X
  629. X        if (Read(fh, buf, size) != size) {
  630. X            Puts("...Error reading extension block function code.");
  631. X            return TRUE;
  632. X        }
  633. X    }
  634. X}
  635. END_OF_FILE
  636. if test 755 -ne `wc -c <'extensions.c'`; then
  637.     echo shar: \"'extensions.c'\" unpacked with wrong size!
  638. fi
  639. # end of 'extensions.c'
  640. fi
  641. if test -f 'giftosham.c' -a "${1}" != "-c" ; then 
  642.   echo shar: Will not clobber existing file \"'giftosham.c'\"
  643. else
  644. echo shar: Extracting \"'giftosham.c'\" \(5232 characters\)
  645. sed "s/^X//" >'giftosham.c' <<'END_OF_FILE'
  646. X/* Copyright 1990 by Christopher A. Wichura.
  647. X   See file GIFMachine.doc for full description of rights.
  648. X*/
  649. X
  650. X#include "GIFMachine.h"
  651. X
  652. Xextern struct GIFdescriptor gdesc;
  653. XEXTERNBITPLANE;
  654. X
  655. Xextern UWORD MasterColourTable[MAXCOLOURS];
  656. X
  657. Xextern char *AbortMsg;
  658. X
  659. Xextern BOOL Laced;
  660. X
  661. XUWORD *SHAMmem;
  662. X
  663. Xstruct rgb {
  664. X    UBYTE rgb_Red;
  665. X    UBYTE rgb_Green;
  666. X    UBYTE rgb_Blue;
  667. X} Palette[16];
  668. X
  669. Xstatic UWORD ColourBuf[MAXCOLOURS];
  670. Xstatic UBYTE PaletteBuf[MAXCOLOURS];
  671. Xstatic ULONG ErrBuf[MAXCOLOURS];
  672. X
  673. X#define ISLACED (Laced && (y != gdesc.gd_Height - 1))
  674. X
  675. Xvoid GIFtoSHAM(void)
  676. X{
  677. X    register UWORD x;
  678. X    register UWORD current;
  679. X    register int index;
  680. X    register int index2;
  681. X    ULONG error;
  682. X    UWORD y;
  683. X    int Pal;
  684. X    int ShamIndex;
  685. X    int colours;
  686. X
  687. X    ULONG TotalErr, LineErr;
  688. X
  689. X    ULONG bestpal;
  690. X    ULONG besterr;
  691. X
  692. X    UBYTE CurrentRed,  CurrentGreen,  CurrentBlue;
  693. X    UBYTE PreviousRed, PreviousGreen, PreviousBlue;
  694. X
  695. X    Printf("...Converting to SHAM format.\n......Line");
  696. X
  697. X    ShamIndex = TotalErr = 0;
  698. X
  699. X    /* palette zero is always the background colour.  regardless of
  700. X       what the GIF specified for the background, we always use black.
  701. X       this is a kludge to get around a hardware `feature' that causes
  702. X       all overscanned screens to have a black background regardless
  703. X       of what the background was specified to be.
  704. X    */
  705. X
  706. X    Palette[0].rgb_Red = Palette[0].rgb_Green = Palette[0].rgb_Blue = 0;
  707. X
  708. X    for (y = 0; y < gdesc.gd_Height; y += (ISLACED ? 2 : 1)) {
  709. X        if (ISLACED)
  710. X            Printf("s %5ld-%5ld", y, y + 1);
  711. X        else
  712. X            Printf(" %5ld", y);
  713. X
  714. X        if (CheckAbort(NULL)) {
  715. X            Printf("\n%s\n", AbortMsg);
  716. X            XCEXIT(ABORTEXITVAL);
  717. X        }
  718. X
  719. X        memset((char *)ColourBuf, 0, sizeof(ColourBuf));
  720. X
  721. X        for (colours = index2 = 0; index2 < (ISLACED ? 2 : 1); index2++)
  722. X            for (x = 0; x < gdesc.gd_Width; x++) {
  723. X                current = GetValue(x, y + index2);
  724. X
  725. X                if (ColourBuf[current]++ == 0)
  726. X                    colours++;
  727. X            }
  728. X
  729. X        Printf(", %4ld unique colours", colours);
  730. X
  731. X        memset((char *)PaletteBuf, 0, sizeof(PaletteBuf));
  732. X
  733. X        for (index = 0; index < MAXCOLOURS; index++) {
  734. X            if (ColourBuf[index] == 0)
  735. X                continue;
  736. X
  737. X            ErrBuf[index] = RGBdiff(GetRed(index),
  738. X                        GetGreen(index),
  739. X                        GetBlue(index),
  740. X                        Palette[0].rgb_Red,
  741. X                        Palette[0].rgb_Green,
  742. X                        Palette[0].rgb_Blue);
  743. X        }
  744. X
  745. X        for (Pal = 1; Pal < 16; Pal++) {
  746. X            for (besterr = index = 0; index < MAXCOLOURS; index++) {
  747. X                if (ColourBuf[index] == 0)
  748. X                    continue;
  749. X
  750. X                if (ErrBuf[index] * ColourBuf[index] >= besterr) {
  751. X                    bestpal = index;
  752. X                    besterr = ErrBuf[index] * ColourBuf[index];
  753. X                }
  754. X            }
  755. X
  756. X            Palette[Pal].rgb_Red   = GetRed(bestpal);
  757. X            Palette[Pal].rgb_Green = GetGreen(bestpal);
  758. X            Palette[Pal].rgb_Blue  = GetBlue(bestpal);
  759. X
  760. X            for (index = 0; index < MAXCOLOURS; index++) {
  761. X                if (ColourBuf[index] == 0)
  762. X                    continue;
  763. X
  764. X                error = RGBdiff(GetRed(index),
  765. X                        GetGreen(index),
  766. X                        GetBlue(index),
  767. X                        Palette[Pal].rgb_Red,
  768. X                        Palette[Pal].rgb_Green,
  769. X                        Palette[Pal].rgb_Blue);
  770. X
  771. X                if (error < ErrBuf[index]) {
  772. X                    ErrBuf[index] = error;
  773. X                    PaletteBuf[index] = Pal;
  774. X                }
  775. X            }
  776. X        }
  777. X
  778. X        for (index = 0; index < 16; index++)
  779. X            SHAMmem[ShamIndex++] = (UWORD)(
  780. X                Palette[index].rgb_Red   << 8 |
  781. X                Palette[index].rgb_Green << 4 |
  782. X                Palette[index].rgb_Blue);
  783. X
  784. X        for (index2 = 0; index2 < (ISLACED ? 2 : 1); index2++) {
  785. X            PreviousRed   = Palette[0].rgb_Red;
  786. X            PreviousGreen = Palette[0].rgb_Green;
  787. X            PreviousBlue  = Palette[0].rgb_Blue;
  788. X
  789. X            for (LineErr = x = 0; x < gdesc.gd_Width; x++) {
  790. X                current = GetValue(x, y + index2);
  791. X
  792. X                CurrentRed   = GetRed(current);
  793. X                CurrentGreen = GetGreen(current);
  794. X                CurrentBlue  = GetBlue(current);
  795. X
  796. X                besterr = ErrBuf[current];
  797. X                bestpal = PaletteBuf[current];
  798. X
  799. X                error = RGBdiff(
  800. X                    CurrentRed,
  801. X                    CurrentGreen,
  802. X                    CurrentBlue,
  803. X                    CurrentRed,
  804. X                    PreviousGreen,
  805. X                    PreviousBlue);
  806. X
  807. X                if (error < besterr) {
  808. X                    besterr = error;
  809. X                    bestpal = 16;
  810. X                }
  811. X
  812. X                error = RGBdiff(
  813. X                    CurrentRed,
  814. X                    CurrentGreen,
  815. X                    CurrentBlue,
  816. X                    PreviousRed,
  817. X                    CurrentGreen,
  818. X                    PreviousBlue);
  819. X
  820. X                if (error < besterr) {
  821. X                    besterr = error;
  822. X                    bestpal = 17;
  823. X                }
  824. X
  825. X                error = RGBdiff(
  826. X                    CurrentRed,
  827. X                    CurrentGreen,
  828. X                    CurrentBlue,
  829. X                    PreviousRed,
  830. X                    PreviousGreen,
  831. X                    CurrentBlue);
  832. X
  833. X                if (error < besterr) {
  834. X                    besterr = error;
  835. X                    bestpal = 18;
  836. X                }
  837. X
  838. X                if (bestpal < 16) {
  839. X                    PutValue(x, y + index2, bestpal);
  840. X
  841. X                    PreviousRed   = Palette[bestpal].rgb_Red;
  842. X                    PreviousGreen = Palette[bestpal].rgb_Green;
  843. X                    PreviousBlue  = Palette[bestpal].rgb_Blue;
  844. X                } else if (bestpal == 16) {
  845. X                    PutValue(x, y + index2, CurrentRed | 0x20);
  846. X
  847. X                    PreviousRed = CurrentRed;
  848. X                } else if (bestpal == 17) {
  849. X                    PutValue(x, y + index2, CurrentGreen | 0x30);
  850. X
  851. X                    PreviousGreen = CurrentGreen;
  852. X                } else {
  853. X                    PutValue(x, y + index2, CurrentBlue | 0x10);
  854. X
  855. X                    PreviousBlue = CurrentBlue;
  856. X                }
  857. X
  858. X                LineErr += besterr;
  859. X            }
  860. X
  861. X            TotalErr += LineErr;
  862. X        }
  863. X
  864. X        Printf("\x9B" "%sD\x9BK", (ISLACED ? "34" : "27"));
  865. X    }
  866. X
  867. X    {
  868. X        ULONG    ErrPerPixel;
  869. X        char    TextBuf[10];
  870. X
  871. X        ErrPerPixel = ((TotalErr / gdesc.gd_Height) * 1000) / gdesc.gd_Width;
  872. X        SPrintf(TextBuf, "%ld.%03ld", ErrPerPixel / 1000, ErrPerPixel % 1000);
  873. X
  874. X        Printf("\x9B" "5DTotal colour error = %ld, Mean per line = %ld, Per pixel = %s.\n",
  875. X            TotalErr, TotalErr / gdesc.gd_Height, TextBuf);
  876. X    }
  877. X}
  878. END_OF_FILE
  879. if test 5232 -ne `wc -c <'giftosham.c'`; then
  880.     echo shar: \"'giftosham.c'\" unpacked with wrong size!
  881. fi
  882. # end of 'giftosham.c'
  883. fi
  884. if test -f 'lmkfile' -a "${1}" != "-c" ; then 
  885.   echo shar: Will not clobber existing file \"'lmkfile'\"
  886. else
  887. echo shar: Extracting \"'lmkfile'\" \(1035 characters\)
  888. sed "s/^X//" >'lmkfile' <<'END_OF_FILE'
  889. X# lmkfile for GIFMachine
  890. X# (c) 1990 by Christopher A. Wichura (caw@miroc.chi.il.us)
  891. X
  892. XCPU = -m0
  893. XDEBUG = -d2
  894. XCFLAGS = $(DEBUG) $(CPU) -v -cs -rr -fid -O
  895. X
  896. XND = NODEBUG
  897. XLFLAGS = $(ND) SMALLCODE SMALLDATA
  898. X
  899. XHDR = GIFMachine.h
  900. X
  901. XOBJS = startup.o main.o warncli.o doimage.o extensions.o writeiff.o colourlist.o stripborder.o xcomp.o rgbdiff.o giftosham.o
  902. XLIBS = LIB:ARP.lib LIB:LCR.lib LIB:amiga.lib
  903. X
  904. X.c.o:
  905. X    LC $(CFLAGS) $*
  906. X
  907. X.a.o:
  908. X    ASM -iINCLUDE: $*
  909. X
  910. XGIFMachine: $(OBJS)
  911. X    BLink <WITH < (GIFMachine.lnk)
  912. XFROM $(OBJS)
  913. XTO GIFMachine
  914. XLIB $(LIBS)
  915. X$(LFLAGS)
  916. X<
  917. X
  918. Xmain.o: main.c $(HDR)
  919. X    LC $(CFLAGS) main
  920. X
  921. Xdoimage.o: doimage.c $(HDR)
  922. X    LC $(CFLAGS) doimage
  923. X
  924. Xextensions.o: extensions.c $(HDR)
  925. X    LC $(CFLAGS) extensions
  926. X
  927. Xwriteiff.o: writeiff.c $(HDR)
  928. X    LC $(CFLAGS) writeiff
  929. X
  930. Xcolourlist.o: colourlist.c $(HDR)
  931. X    LC $(CFLAGS) colourlist
  932. X
  933. Xstripborder.o: stripborder.c $(HDR)
  934. X    LC $(CFLAGS) stripborder
  935. X
  936. Xxcomp.o: xcomp.c $(HDR)
  937. X        LC $(CFLAGS) xcomp
  938. X
  939. Xgiftosham.o: giftosham.c $(HDR)
  940. X    LC $(CFLAGS) giftosham
  941. X
  942. Xrgbdiff.o: rgbdiff.c $(HDR)
  943. X    LC $(CFLAGS) rgbdiff
  944. END_OF_FILE
  945. if test 1035 -ne `wc -c <'lmkfile'`; then
  946.     echo shar: \"'lmkfile'\" unpacked with wrong size!
  947. fi
  948. # end of 'lmkfile'
  949. fi
  950. if test -f 'main.c' -a "${1}" != "-c" ; then 
  951.   echo shar: Will not clobber existing file \"'main.c'\"
  952. else
  953. echo shar: Extracting \"'main.c'\" \(9441 characters\)
  954. sed "s/^X//" >'main.c' <<'END_OF_FILE'
  955. X/* Copyright 1990 by Christopher A. Wichura.
  956. X   See file GIFMachine.doc for full description of rights.
  957. X*/
  958. X
  959. X#include "GIFMachine.h"
  960. X#include <workbench/startup.h>
  961. X
  962. Xstruct GIFdescriptor gdesc;
  963. X
  964. XUWORD **BitPlane;
  965. XUWORD GlobalColourTable[256];
  966. X
  967. Xextern UWORD *SHAMmem;
  968. X
  969. Xextern BYTE *PlaneBuf;
  970. X
  971. Xextern BOOL Laced;
  972. X
  973. Xextern UBYTE *Planes[6];
  974. X
  975. XULONG ImageNumber;
  976. Xextern UWORD TotalColours;
  977. X
  978. X/* here we have some defines relating to our GADS call */
  979. X#define ESC "\x9B"
  980. X#define GIFMACH ESC "33;42mGIFMachine" ESC "32;40m"
  981. X#define ARP_HELP    GIFMACH " v1.0 \xA9 1990 by " \
  982. X            ESC "4;33;42mChristopher A. Wichura" \
  983. X            ESC "0;33;40m (" ESC "32mcaw" ESC "33m@" \
  984. X            ESC "32mmiroc.chi.il.us" ESC "33m)\n" \
  985. X            ESC "31mUsage:     " GIFMACH " <" ESC \
  986. X            "31mGIFfile(s)" ESC "32m> [" ESC "33mTO " \
  987. X            ESC "31mDirectory | File" ESC "32m] [" \
  988. X            ESC "33mALL" ESC "32m]\n                      [" \
  989. X            ESC "33mNOBORDER " ESC "32m<" ESC "31mLine " \
  990. X            "Thresh" ESC "32m>] [" ESC "33mXCOMP" \
  991. X            ESC "32m]\n" ESC "31m"
  992. X
  993. X#define ARP_TEMPLATE "GIFfiles/...,TO/k,ALL/s,NOBORDER/k,XCOMP/s"
  994. X#define ARG_FILES  0
  995. X#define ARG_TO     1
  996. X#define ARG_ALL    2
  997. X#define ARG_NOBORD 3
  998. X#define ARG_XCOMP  4
  999. X#define ARG_sizeof 5
  1000. X
  1001. X/* we will make the argument array global so that other modules can get at
  1002. X   the ARG_TO, ARG_ALL and ARG_XCOMP fields easily */
  1003. Xchar *ArgArray[ARG_sizeof];
  1004. XBOOL ArgToIsDir;
  1005. X
  1006. Xint NoBorderLineThresh = 0;
  1007. X
  1008. X/* this flag says if we scaled the image */
  1009. XBOOL DidXComp;
  1010. X
  1011. X/* we print this when the user hits the break key */
  1012. Xchar *AbortMsg = "*** User Interruption!";
  1013. X
  1014. X/* storage for the math library base */
  1015. Xstruct Library *MathIeeeDoubBasBase;
  1016. X
  1017. X/* here we have our main routine */
  1018. Xint __regargs main(char *cmdptr, int cmdlen, struct WBStartup *WBMsg)
  1019. X{
  1020. X    register char **FilesPtr;
  1021. X
  1022. X    if (WBMsg) {
  1023. X        WarnMustUseCLI();
  1024. X        XCEXIT(5);
  1025. X    }
  1026. X
  1027. X    if (!(MathIeeeDoubBasBase = ArpOpenLibrary("mathieeedoubbas.library", 0))) {
  1028. X        Puts("Unable to access mathieeedoubbas.library!");
  1029. X        XCEXIT(5);
  1030. X    }
  1031. X
  1032. X    memset((char *)ArgArray, 0, sizeof(ArgArray));
  1033. X
  1034. X    if (GADS(cmdptr, cmdlen, ARP_HELP, ArgArray, ARP_TEMPLATE) < 0) {
  1035. X        Puts(ArgArray[0]);
  1036. X        XCEXIT(5);
  1037. X    }
  1038. X
  1039. X    if (ArgArray[ARG_TO])
  1040. X        ArgToIsDir = IsDir(ArgArray[ARG_TO]);
  1041. X
  1042. X    if (ArgArray[ARG_NOBORD]) {
  1043. X        NoBorderLineThresh = Atol(ArgArray[ARG_NOBORD]);
  1044. X        if (NoBorderLineThresh < 0 || NoBorderLineThresh > 100) {
  1045. X            Puts("Invalid NOBORDER line threshhold specified.");
  1046. X            XCEXIT(3);
  1047. X        }
  1048. X    }
  1049. X
  1050. X    if (!(FilesPtr = (char **)ArgArray[ARG_FILES])) {
  1051. X        Puts("No GIF files selected.");
  1052. X        XCEXIT(3);
  1053. X    }
  1054. X
  1055. X    InitDiff();    /* one time init for the RGBdiff function */
  1056. X
  1057. X    while (*FilesPtr)
  1058. X        DoPattern(*FilesPtr++);    
  1059. X}
  1060. X
  1061. X/* this will walk through a pattern doing conversions */
  1062. Xvoid DoPattern(char *pat)
  1063. X{
  1064. X    register struct Anchor {
  1065. X        struct AnchorPath APath;
  1066. X        char              Path[256];
  1067. X    } *anchor;
  1068. X    register int error;
  1069. X
  1070. X    if (!(anchor = (struct Anchor *)ArpAlloc(sizeof(struct Anchor)))) {
  1071. X        Puts("Out of memory!");
  1072. X        XCEXIT(10);
  1073. X    }
  1074. X
  1075. X    anchor->APath.ap_StrLen = sizeof(anchor->Path);
  1076. X    anchor->APath.ap_Flags = APF_DoWild;
  1077. X    anchor->APath.ap_BreakBits = SIGBREAKF_CTRL_C;
  1078. X
  1079. X    error = FindFirst(pat, &anchor->APath);
  1080. X
  1081. X    while (!error) {
  1082. X        if (anchor->APath.ap_Info.fib_DirEntryType > 0) {
  1083. X            if (ArgArray[ARG_ALL]) {
  1084. X                if (!(anchor->APath.ap_Flags & APF_DidDir))
  1085. X                    anchor->APath.ap_Flags |= APF_DoDir;
  1086. X                anchor->APath.ap_Flags &= ~APF_DidDir;
  1087. X            }
  1088. X        } else
  1089. X            Convert(anchor->APath.ap_Buf);
  1090. X
  1091. X        error = FindNext(&anchor->APath);
  1092. X    }
  1093. X
  1094. X    FreeAnchorChain(&anchor->APath);
  1095. X
  1096. X    switch(error) {
  1097. X        case ERROR_BREAK:
  1098. X            Puts(AbortMsg);
  1099. X            XCEXIT(ABORTEXITVAL);
  1100. X            break;
  1101. X
  1102. X        case ERROR_OBJECT_NOT_FOUND:
  1103. X            Puts("File not found.");
  1104. X            break;
  1105. X
  1106. X        case ERROR_BUFFER_OVERFLOW:
  1107. X            Puts("Path too long!");
  1108. X            break;
  1109. X
  1110. X        case ERROR_NO_MORE_ENTRIES:    /* normal termination */
  1111. X            break;
  1112. X
  1113. X        default:
  1114. X            Printf("I/O Error #%ld!\n", error);
  1115. X            break;
  1116. X    }
  1117. X
  1118. X    FreeTrackedItem((struct DefaultTracker *)anchor);
  1119. X}
  1120. X
  1121. X/* here we have the routine that gets ready to do the conversion */
  1122. Xvoid Convert(char *name)
  1123. X{
  1124. X    register BPTR fh;
  1125. X    register int index;
  1126. X    char *basename;
  1127. X    char *ptr;
  1128. X    char sig[7];
  1129. X    UBYTE buf[3];
  1130. X    int size;
  1131. X    int error;
  1132. X    int colours;
  1133. X    UWORD NewBackground;
  1134. X
  1135. X    struct DateStamp StartTime, EndTime;
  1136. X
  1137. X    if (!CreateTaskResList()) {
  1138. X        Puts("Fatal tracker error!");
  1139. X        XCEXIT(10);
  1140. X    }
  1141. X
  1142. X    if (!(fh = ArpOpen(name, MODE_OLDFILE))) {
  1143. X        Printf("Error #%ld trying to open %s...\n", IoErr(), name);
  1144. X        goto LeaveConvert;
  1145. X    }
  1146. X
  1147. X    sig[6] = NULL;
  1148. X
  1149. X    if (Read(fh, sig, 6) != 6 || strncmp("GIF", sig, 3)) {
  1150. X        Printf("%s is not a GIF file...\n", name);
  1151. X        goto LeaveConvert;
  1152. X    }
  1153. X
  1154. X    Printf("Converting %s ", name);
  1155. X
  1156. X    basename = BaseName(name);
  1157. X    ptr = basename + strlen(basename) - 4;
  1158. X
  1159. X    if (!strnicmp(".gif", ptr, 4))
  1160. X        *ptr = NULL;
  1161. X
  1162. X    size = strlen(basename) + 6;
  1163. X
  1164. X    if (ArgArray[ARG_TO]) {
  1165. X        if (ArgToIsDir)
  1166. X            size += strlen(ArgArray[ARG_TO]) + 1;
  1167. X        else
  1168. X            size = strlen(ArgArray[ARG_TO]) + 1;
  1169. X    }
  1170. X
  1171. X    if (!(ptr = ArpAlloc(size))) {
  1172. X        Puts("... Out of memory!");
  1173. X        goto LeaveConvert;
  1174. X    }
  1175. X
  1176. X    if (ArgArray[ARG_TO]) {
  1177. X        strcpy(ptr, ArgArray[ARG_TO]);
  1178. X
  1179. X        if (ArgToIsDir) {
  1180. X            TackOn(ptr, basename);
  1181. X            strcat(ptr, ".sham");
  1182. X        }
  1183. X    } else {
  1184. X        strcpy(ptr, basename);
  1185. X        strcat(ptr, ".sham");
  1186. X    }
  1187. X
  1188. X    Printf("to %s...\n", ptr);
  1189. X
  1190. X    DateStamp((LONG *)&StartTime);
  1191. X
  1192. X    if (Read(fh, (char *)&gdesc, 7) != 7) {
  1193. X        Puts("Error reading screen descriptor.");
  1194. X        goto LeaveConvert;
  1195. X    }
  1196. X
  1197. X    FlipWord(&gdesc.gd_Width);
  1198. X    FlipWord(&gdesc.gd_Height);
  1199. X
  1200. X    Printf("Signature = \"%s\", Width = %ld, Height = %ld\n",
  1201. X        sig, gdesc.gd_Width, gdesc.gd_Height);
  1202. X
  1203. X    DidXComp = TotalColours = 0;
  1204. X    colours = 1L << ((gdesc.gd_ColInfo & 7) + 1);
  1205. X
  1206. X    if (!(gdesc.gd_ColInfo & 1L << 7)) {
  1207. X        Puts("No global colour map supplied, using internal.");
  1208. X
  1209. X        for (index = 0; index < colours; index++) {
  1210. X            buf[0] = buf[1] = buf[2] = CVRTGIF(index);
  1211. X            GlobalColourTable[index] = AddColour(buf);
  1212. X        }
  1213. X    } else {
  1214. X        Printf("Global colour map contains %ld entries.\n", colours);
  1215. X
  1216. X        for (index = 0; index < colours; index++) {
  1217. X            if (Read(fh, buf, 3) != 3) {
  1218. X                Printf("Error reading global colour #%ld.\n",
  1219. X                    index);
  1220. X                goto LeaveConvert;
  1221. X            }
  1222. X
  1223. X            GlobalColourTable[index] = AddColour(buf);
  1224. X            if (index == gdesc.gd_BackGround)
  1225. X                NewBackground = GlobalColourTable[index];
  1226. X        }
  1227. X
  1228. X        gdesc.gd_BackGround = NewBackground;
  1229. X    }
  1230. X
  1231. X    size = ((gdesc.gd_Width + 7) / 8) + 1;
  1232. X    size += (size + 127) >> 7;
  1233. X
  1234. X    if (!(BitPlane = (UWORD **)ArpAlloc(gdesc.gd_Height * sizeof(UWORD *))) ||
  1235. X        !(SHAMmem  = (UWORD *)ArpAlloc(gdesc.gd_Height * 16 * sizeof(UWORD))) ||
  1236. X        !(PlaneBuf  = (BYTE *)ArpAlloc(size))) {
  1237. X        Puts("Out of memory trying to allocate picture.");
  1238. X        goto LeaveConvert;
  1239. X    }
  1240. X
  1241. X    size = (gdesc.gd_Width + 1) * sizeof(UWORD);
  1242. X
  1243. X    for (index = 0; index < gdesc.gd_Height; index++)
  1244. X        if (!(BitPlane[index] = (UWORD *)ArpAlloc(size))) {
  1245. X            Puts("Out of memory trying to allocate picture.");
  1246. X            goto LeaveConvert;
  1247. X        }
  1248. X
  1249. X    size = ((gdesc.gd_Width + 7) / 8) + 1;
  1250. X    for (index = 0; index < 6; index++)
  1251. X        if (!(Planes[index] = (UBYTE *)ArpAlloc(size))) {
  1252. X            Puts("Out of memory trying to allocate picture.");
  1253. X            goto LeaveConvert;
  1254. X        }
  1255. X
  1256. X    ImageNumber = 1;
  1257. X
  1258. X    /* at this point we start looking for images, extensions or the gif
  1259. X       terminator.  we call the appropriate routine as we find each. */
  1260. X
  1261. X    for (error = FALSE; error == FALSE;) {
  1262. X        if (Read(fh, buf, 1) != 1) {
  1263. X            Puts("...Error reading GIF file.");
  1264. X            break;
  1265. X        }
  1266. X
  1267. X        switch(buf[0]) {
  1268. X            case GIF_IMAGE:
  1269. X                error = DoImage(fh);
  1270. X                break;
  1271. X
  1272. X            case GIF_EXTENSION:
  1273. X                error = DoExtension(fh);
  1274. X                break;
  1275. X
  1276. X            case GIF_TERMINATOR:
  1277. X                Printf("...%ld unique colours used by GIF file.\n",
  1278. X                    TotalColours);
  1279. X
  1280. X                if (ArgArray[ARG_NOBORD])
  1281. X                    StripBorder();
  1282. X
  1283. X                if (ArgArray[ARG_XCOMP] && ISTOOBIG) {
  1284. X                    DoXComp();
  1285. X                    DidXComp = 1;
  1286. X                }
  1287. X
  1288. X                if (gdesc.gd_Height > 200 && (!ISTOOBIG || DidXComp))
  1289. X                    Laced = TRUE;
  1290. X                else
  1291. X                    Laced = FALSE;
  1292. X
  1293. X                GIFtoSHAM();
  1294. X                error = WriteIFF(ptr);
  1295. X                break;
  1296. X
  1297. X            default:
  1298. X                Printf("...Unknown directive #%ld encountered.\n",
  1299. X                    buf[0]);
  1300. X                error = TRUE;
  1301. X        }
  1302. X    }
  1303. X
  1304. X    DateStamp((ULONG *)&EndTime);
  1305. X
  1306. X    {
  1307. X        register ULONG Hours;
  1308. X        register ULONG Minutes;
  1309. X        register ULONG Seconds;
  1310. X        register ULONG Seconds2;
  1311. X    
  1312. X        Seconds = (EndTime.ds_Days * 86400) + (EndTime.ds_Minute * 60) + (EndTime.ds_Tick / TICKS_PER_SECOND);
  1313. X        Seconds2 = (StartTime.ds_Days * 86400) + (StartTime.ds_Minute * 60) + (StartTime.ds_Tick / TICKS_PER_SECOND);
  1314. X
  1315. X        Seconds -= Seconds2;
  1316. X
  1317. X        Hours = Seconds / 3600;
  1318. X        Seconds -= Hours * 3600;
  1319. X
  1320. X        Minutes = Seconds / 60;
  1321. X        Seconds -= Minutes * 60;
  1322. X
  1323. X        Printf("...Conversion time was %ld hour%s, %ld minute%s and %ld second%s.\n",
  1324. X            Hours, (Hours != 1 ? "s" : ""),
  1325. X            Minutes, (Minutes != 1 ? "s" : ""),
  1326. X            Seconds, (Seconds != 1 ? "s" : ""));
  1327. X    }
  1328. X
  1329. XLeaveConvert:
  1330. X    FreeTaskResList();
  1331. X}
  1332. X
  1333. X/* this will check to see if we have a directory or not */
  1334. XBOOL IsDir(char *name)
  1335. X{
  1336. X    register BPTR lock;
  1337. X    register BOOL result = FALSE;
  1338. X
  1339. X    /* kludge to word allign our FileInfoBlock to avoid having to */
  1340. X    /* call AllocMem() for it.  Gotten from a UseNet message.     */
  1341. X
  1342. X    char c_fib[sizeof(struct FileInfoBlock) + 3];
  1343. X    struct FileInfoBlock *fib = (struct FileInfoBlock *)
  1344. X        ((unsigned long)(((unsigned long)c_fib+3)>>2)<<2);
  1345. X
  1346. X    if (lock = Lock(name, ACCESS_READ)) {
  1347. X        if (Examine(lock, fib)) {
  1348. X            if (fib->fib_DirEntryType > 0)
  1349. X                result = TRUE;
  1350. X        }
  1351. X        UnLock(lock);
  1352. X    }
  1353. X
  1354. X    return result;
  1355. X}
  1356. X
  1357. X/* this will convert a word from LSB/MSB to MSB/LSB */
  1358. Xvoid FlipWord(UWORD *word)
  1359. X{
  1360. X    register UBYTE swap1;
  1361. X    register UBYTE swap2;
  1362. X
  1363. X    swap1 = *word & 0xFF;
  1364. X    swap2 = (*word & 0xFF00) >> 8;
  1365. X    *word = swap1 << 8 | swap2;
  1366. X}
  1367. END_OF_FILE
  1368. if test 9441 -ne `wc -c <'main.c'`; then
  1369.     echo shar: \"'main.c'\" unpacked with wrong size!
  1370. fi
  1371. # end of 'main.c'
  1372. fi
  1373. if test -f 'rgbdiff.c' -a "${1}" != "-c" ; then 
  1374.   echo shar: Will not clobber existing file \"'rgbdiff.c'\"
  1375. else
  1376. echo shar: Extracting \"'rgbdiff.c'\" \(876 characters\)
  1377. sed "s/^X//" >'rgbdiff.c' <<'END_OF_FILE'
  1378. X/* Note:  this colour comparison routine was snitched from HamSharp.
  1379. X
  1380. X   This has the side effect of allowing one to compare colour errors gotten
  1381. X   with GIFMachine to those gotten with (S)HamSharp.
  1382. X*/
  1383. X
  1384. X#include "GIFMachine.h"
  1385. X
  1386. Xstatic UBYTE Diff[16][16];
  1387. Xstatic UBYTE Intensity[16][16][16];
  1388. X
  1389. Xextern struct Library *MathIeeeDoubBasBase;
  1390. X
  1391. Xvoid InitDiff(void)
  1392. X{
  1393. X    register int i;
  1394. X    register int j;
  1395. X    register int r;
  1396. X    register int g;
  1397. X    register int b;
  1398. X
  1399. X    for (i = 0; i < 16; i++)
  1400. X        for (j = 0; j < 16; j++)
  1401. X            Diff[i][j] = (i - j) * (i - j);
  1402. X
  1403. X    for (r = 0; r < 16; r++)
  1404. X        for (g = 0; g < 16; g++)
  1405. X            for (b = 0; b < 16; b++)
  1406. X                Intensity[r][g][b] = (int)(.299 * r + .587 * g + .114 * b);
  1407. X}
  1408. X
  1409. XULONG RGBdiff(UBYTE r1, UBYTE g1, UBYTE b1, UBYTE r2, UBYTE g2, UBYTE b2)
  1410. X{
  1411. X    return (ULONG)(Diff[Intensity[r1][g1][b1]][Intensity[r2][g2][b2]] +
  1412. X        Diff[r1][r2] + Diff[g1][g2] + Diff[b1][b2]);
  1413. X}
  1414. END_OF_FILE
  1415. if test 876 -ne `wc -c <'rgbdiff.c'`; then
  1416.     echo shar: \"'rgbdiff.c'\" unpacked with wrong size!
  1417. fi
  1418. # end of 'rgbdiff.c'
  1419. fi
  1420. if test -f 'startup.a' -a "${1}" != "-c" ; then 
  1421.   echo shar: Will not clobber existing file \"'startup.a'\"
  1422. else
  1423. echo shar: Extracting \"'startup.a'\" \(4258 characters\)
  1424. sed "s/^X//" >'startup.a' <<'END_OF_FILE'
  1425. X INCLUDE "libraries/ArpBase.i"
  1426. X INCLUDE "exec/execbase.i"
  1427. X INCLUDE "libraries/dosextens.i"
  1428. X
  1429. X XREF @main
  1430. X
  1431. X XREF _LVOOpenLibrary
  1432. X XREF _LVOCloseLibrary
  1433. X XREF _LVOSetSignal
  1434. X XREF _LVOForbid
  1435. X XREF _LVOWaitPort
  1436. X XREF _LVOGetMsg
  1437. X XREF _LVOReplyMsg
  1438. X
  1439. X XREF _LinkerDB
  1440. X XREF __BSSBAS
  1441. X XREF __BSSLEN
  1442. X XREF _RESLEN
  1443. X XREF _RESBASE
  1444. X XREF _NEWDATAL
  1445. X
  1446. X XREF _AbsExecBase
  1447. X
  1448. XCALL    MACRO
  1449. X    jsr _LVO\1(a6)
  1450. X    ENDM
  1451. X
  1452. X  SECTION StartCode,CODE
  1453. X
  1454. X; arp resident tag goes here
  1455. X    RESIDENT 10*1024
  1456. X
  1457. Xinit:
  1458. X    movem.l    d0/a0,-(sp)
  1459. X
  1460. X; first off we will check for our workbench message, if any.  we will store
  1461. X; the pointer to it in d7 temporarily until we actually copy the data
  1462. X; segment over.  otherwise we wouldn't be residentiable.
  1463. X
  1464. X    moveq    #0,d7        ; clear out longword
  1465. X
  1466. X; get address of our task
  1467. X    move.l    _AbsExecBase.W,a6
  1468. X    move.l    ThisTask(a6),a3
  1469. X
  1470. X; clear any pending signals
  1471. X    moveq    #0,d0
  1472. X    move.l    #$00003000,d1
  1473. X    CALL    SetSignal
  1474. X
  1475. X; check for workbench message
  1476. X    tst.l    pr_CLI(a3)
  1477. X    bne.s    FromCLI
  1478. X
  1479. X    lea    pr_MsgPort(a3),a0
  1480. X    CALL    WaitPort
  1481. X    lea    pr_MsgPort(a3),a0
  1482. X    CALL    GetMsg
  1483. X    move.l    d0,d7
  1484. X
  1485. XFromCLI:
  1486. X    lea    ARPlib(pc),a1
  1487. X    moveq    #ArpVersion,d0
  1488. X    CALL    OpenLibrary
  1489. X    tst.l    d0
  1490. X    bne.s    ARPmain
  1491. X
  1492. X    lea    DOSlib(pc),a1
  1493. X    CALL    OpenLibrary
  1494. X    tst.l    d0
  1495. X    beq.s    bomb
  1496. X
  1497. X    move.l    d0,a6
  1498. X    CALL    Output
  1499. X    move.l    d0,d1
  1500. X    beq.s    bomb
  1501. X
  1502. X    lea    Msg1(pc),a0
  1503. X    move.l    a0,d2
  1504. X    moveq    #Msg1Len,d3
  1505. X    CALL    Write
  1506. X
  1507. X    move.l    a6,a1
  1508. X    move.l    _AbsExecBase.W,a6
  1509. X    CALL    CloseLibrary
  1510. X
  1511. Xbomb:    addq.l    #8,sp        ; pop d0/a0 off stack
  1512. X
  1513. X    move.l    d7,d0        ; check if we have a workbench startup
  1514. X    bsr    ReplyWB        ; message and reply it if so
  1515. X
  1516. X    moveq    #0,d0        ; set an exit code
  1517. X    rts
  1518. X
  1519. XARPmain:
  1520. X    move.l    d0,a6
  1521. X
  1522. X    lea    _LinkerDB,a4
  1523. X    sub.l    #_RESBASE,a4
  1524. X
  1525. X; get mem to hold data and bss stuff
  1526. X    move.l    #_RESLEN,d0
  1527. X    CALL    ArpAlloc
  1528. X    tst.l    d0
  1529. X    bne.s    gotmem
  1530. X
  1531. X; no mem available so bomb out
  1532. X    move.l    d7,d0        ; check for wb startup message and reply
  1533. X    bsr    ReplyWB        ; it if present
  1534. X
  1535. X    addq.l    #8,sp        ; pop d0/a0 off of stack
  1536. X
  1537. X    moveq    #20,d0
  1538. X    moveq    #ERROR_NO_FREE_STORE,d2
  1539. X    CALL    ArpExit
  1540. X
  1541. X; get ready to copy data over into freshly alloced data area
  1542. Xgotmem:    move.l    d0,a0
  1543. X    move.l    d0,a2
  1544. X
  1545. X    move.l    d0,a1
  1546. X    move.l    #_NEWDATAL,d0
  1547. Xcpy:    move.l    (a4)+,(a0)+
  1548. X    subq.l    #1,d0
  1549. X    bne.s    cpy
  1550. X
  1551. X; now do the relocs for resident data
  1552. X    move.l    (a4)+,d0
  1553. Xreloc:    beq.s    nreloc
  1554. X    move.l    a1,a0
  1555. X    add.l    (a4)+,a0
  1556. X    add.l    (a0),a2
  1557. X    move.l    a2,(a0)
  1558. X    move.l    a1,a2
  1559. X    subq.l    #1,d0
  1560. X    bra.s    reloc
  1561. X
  1562. Xnreloc:    move.l    a1,a4
  1563. X    add.l    #_RESBASE,a4
  1564. X
  1565. X; stash some important junk away
  1566. X    move.l    a6,_ArpBase(a4)
  1567. X    move.l    GfxBase(a6),_GfxBase(a4)
  1568. X    move.l    IntuiBase(a6),_IntuitionBase(a4)
  1569. X    move.l    d7,_WBenchMsg(a4)
  1570. X
  1571. X    move.l    _AbsExecBase.W,a6
  1572. X    move.l    a6,_SysBase(a4)
  1573. X    movem.l    sp,__StackPtr(a4)
  1574. X
  1575. X; call our main program.  we call the main routine with the following
  1576. X; arguments:
  1577. X;
  1578. X;   d0 = length of command line
  1579. X;   a0 = pointer to command line
  1580. X;   a1 = pointer to workbench startup message (or NULL)
  1581. X
  1582. X    movem.l    (sp)+,d0/a0
  1583. X    movea.l    d7,a1
  1584. X    jsr    @main
  1585. X    moveq    #0,d0
  1586. X    bra.s    Exit
  1587. X
  1588. X XDEF _XCEXIT
  1589. X_XCEXIT:
  1590. X    move.l    4(sp),d0
  1591. X XDEF @XCEXIT
  1592. X@XCEXIT:
  1593. X
  1594. XExit:    move.l    d0,d2            ; save return code in safe place
  1595. X
  1596. X    move.l    _WBenchMsg(a4),d0    ; check if we need to reply the
  1597. X    bsr    ReplyWB            ; workbench startup message
  1598. X
  1599. X1$    move.l    d2,d0            ; restore return code
  1600. X
  1601. X    move.l    _ArpBase(a4),a6
  1602. X    movea.l    __StackPtr(a4),sp
  1603. X    moveq    #0,d2
  1604. X    CALL    ArpExit
  1605. X
  1606. X; this subroutine is called when we try to check if we need to reply
  1607. X; the workbench message.  This is done because we do this in more than
  1608. X; one place.
  1609. X
  1610. XReplyWB:
  1611. X    move.l    d0,d2
  1612. X    beq.s    1$
  1613. X
  1614. X    move.l    _AbsExecBase.W,a6
  1615. X    CALL    Forbid
  1616. X    movea.l    d2,a1
  1617. X    CALL    ReplyMsg
  1618. X
  1619. X1$    rts
  1620. X
  1621. X; ---- This is the data we need for the startup module.  we don't put it in
  1622. X;      a data segment, though, or it would end up being copied over when we
  1623. X;      clone the data hunk and this stuff isn't needed anywhere else...
  1624. X
  1625. X    IFGE ArpVersion-100
  1626. X     FAIL "You lose: Time to bump version report to 3 digits!"
  1627. X    ENDC
  1628. X
  1629. XDOSlib    dc.b "dos.library",0
  1630. X
  1631. XTEM    SET ArpVersion/10
  1632. XMsg1    dc.b "You need "
  1633. XARPlib    ArpName
  1634. X    dc.b " V",TEM+'0',(ArpVersion-(TEM*10))+'0','+',10,0
  1635. XMsg1Len    EQU *-Msg1
  1636. X    ds.w 0
  1637. X
  1638. X; ---- This is the BBS segment that holds various startup junk for us.
  1639. X
  1640. X   SECTION __MERGED,BSS
  1641. X
  1642. X XDEF _ArpBase
  1643. X XDEF _GfxBase
  1644. X XDEF _SysBase
  1645. X XDEF _IntuitionBase
  1646. X XDEF _WBenchMsg
  1647. X XDEF __StackPtr
  1648. X
  1649. X_ArpBase    ds.b 4
  1650. X_GfxBase    ds.b 4
  1651. X_SysBase    ds.b 4
  1652. X_IntuitionBase    ds.b 4
  1653. X_WBenchMsg    ds.b 4
  1654. X__StackPtr    ds.b 4
  1655. X
  1656. X   END
  1657. END_OF_FILE
  1658. if test 4258 -ne `wc -c <'startup.a'`; then
  1659.     echo shar: \"'startup.a'\" unpacked with wrong size!
  1660. fi
  1661. # end of 'startup.a'
  1662. fi
  1663. if test -f 'stripborder.c' -a "${1}" != "-c" ; then 
  1664.   echo shar: Will not clobber existing file \"'stripborder.c'\"
  1665. else
  1666. echo shar: Extracting \"'stripborder.c'\" \(2650 characters\)
  1667. sed "s/^X//" >'stripborder.c' <<'END_OF_FILE'
  1668. X/* Copyright 1990 by Christopher A. Wichura.
  1669. X   See file GIFMachine.doc for full description of rights.
  1670. X*/
  1671. X
  1672. X#include "GIFMachine.h"
  1673. X
  1674. Xextern struct GIFdescriptor gdesc;
  1675. XEXTERNBITPLANE;
  1676. X
  1677. Xextern char *AbortMsg;
  1678. X
  1679. Xextern int NoBorderLineThresh;
  1680. X
  1681. Xextern UWORD MasterColourTable[MAXCOLOURS];
  1682. X
  1683. Xstatic UWORD BorderCol;
  1684. X
  1685. X#define BorderCheck(a, b) (GetValue(a, b) != BorderCol)
  1686. X
  1687. Xvoid StripBorder(void)
  1688. X{
  1689. X    register UWORD x;
  1690. X    register UWORD y;
  1691. X    register int thresh;
  1692. X    register BOOL breakout;
  1693. X    UWORD LeftEdge, TopEdge;
  1694. X    UWORD Width, Height;
  1695. X    int WidthThresh, HeightThresh;
  1696. X
  1697. X    Puts("...Removing border.");
  1698. X
  1699. X    BorderCol = GetValue(0, 0);
  1700. X
  1701. X    WidthThresh  = NoBorderLineThresh * gdesc.gd_Width  / 100;
  1702. X    HeightThresh = NoBorderLineThresh * gdesc.gd_Height / 100;
  1703. X
  1704. X    for (breakout = y = 0; (y < gdesc.gd_Height) && !breakout; y++) {
  1705. X        for (thresh = x = 0; x < gdesc.gd_Width; x++)
  1706. X            if (BorderCheck(x, y))
  1707. X                if (++thresh > WidthThresh) {
  1708. X                    breakout = TRUE;
  1709. X                    break;
  1710. X                }
  1711. X
  1712. X        if (CheckAbort(NULL)) {
  1713. X            Puts(AbortMsg);
  1714. X            XCEXIT(ABORTEXITVAL);
  1715. X        }
  1716. X    }
  1717. X
  1718. X    TopEdge = y - 1;
  1719. X
  1720. X    for (breakout = 0, y = gdesc.gd_Height - 1; y >= 0 && !breakout; y--) {
  1721. X        for (thresh = x = 0; x < gdesc.gd_Width; x++)
  1722. X            if (BorderCheck(x, y))
  1723. X                if (++thresh > WidthThresh) {
  1724. X                    breakout = TRUE;
  1725. X                    break;
  1726. X                }
  1727. X
  1728. X        if (CheckAbort(NULL)) {
  1729. X            Puts(AbortMsg);
  1730. X            XCEXIT(ABORTEXITVAL);
  1731. X        }
  1732. X    }
  1733. X
  1734. X    Height = y - TopEdge + 2;
  1735. X
  1736. X    for (breakout = x = 0; (x < gdesc.gd_Width) && !breakout; x++) {
  1737. X        for (thresh = y = 0; y < gdesc.gd_Height; y++)
  1738. X            if (BorderCheck(x, y))
  1739. X                if (++thresh > HeightThresh) {
  1740. X                    breakout = TRUE;
  1741. X                    break;
  1742. X                }
  1743. X
  1744. X        if (CheckAbort(NULL)) {
  1745. X            Puts(AbortMsg);
  1746. X            XCEXIT(ABORTEXITVAL);
  1747. X        }
  1748. X    }
  1749. X
  1750. X    LeftEdge = x - 1;
  1751. X
  1752. X    for (breakout = 0, x = gdesc.gd_Width - 1; x >= 0 && !breakout; x--) {
  1753. X        for (thresh = y = 0; y < gdesc.gd_Height; y++)
  1754. X            if (BorderCheck(x, y))
  1755. X                if (++thresh > HeightThresh) {
  1756. X                    breakout = TRUE;
  1757. X                    break;
  1758. X                }
  1759. X
  1760. X        if (CheckAbort(NULL)) {
  1761. X            Puts(AbortMsg);
  1762. X            XCEXIT(ABORTEXITVAL);
  1763. X        }
  1764. X    }
  1765. X
  1766. X    Width = x - LeftEdge + 2;
  1767. X
  1768. X    if ((Width != gdesc.gd_Width) || (Height != gdesc.gd_Height)) {
  1769. X        if (Width < 5 || Height < 5) {
  1770. X            Puts("......Too much of picture would be removed.  Not modified.");
  1771. X            return;
  1772. X        }
  1773. X
  1774. X        for (y = 0; y < Height; y++) {
  1775. X            for (x = 0; x < Width; x++)
  1776. X                PutValue(x, y,
  1777. X                   GetValue((UWORD)(LeftEdge + x),
  1778. X                        (UWORD)(TopEdge + y)));
  1779. X
  1780. X            PutValue(x, y, gdesc.gd_BackGround);
  1781. X
  1782. X            if (CheckAbort(NULL)) {
  1783. X                Puts(AbortMsg);
  1784. X                XCEXIT(ABORTEXITVAL);
  1785. X            }
  1786. X        }
  1787. X
  1788. X        if (Width & 1)
  1789. X            Width++;
  1790. X
  1791. X        Printf("......New width = %ld, New height = %ld\n", Width, Height);
  1792. X        gdesc.gd_Width = Width;
  1793. X        gdesc.gd_Height = Height;
  1794. X    }
  1795. X}
  1796. END_OF_FILE
  1797. if test 2650 -ne `wc -c <'stripborder.c'`; then
  1798.     echo shar: \"'stripborder.c'\" unpacked with wrong size!
  1799. fi
  1800. # end of 'stripborder.c'
  1801. fi
  1802. if test -f 'warncli.c' -a "${1}" != "-c" ; then 
  1803.   echo shar: Will not clobber existing file \"'warncli.c'\"
  1804. else
  1805. echo shar: Extracting \"'warncli.c'\" \(1457 characters\)
  1806. sed "s/^X//" >'warncli.c' <<'END_OF_FILE'
  1807. X/* Copyright 1990 by Christopher A. Wichura.
  1808. X   See file GIFMachine.doc for full description of rights.
  1809. X*/
  1810. X
  1811. X#include <exec/types.h>
  1812. X#include <intuition/intuition.h>
  1813. X#include <graphics/text.h>
  1814. X#include <proto/intuition.h>
  1815. X
  1816. Xstatic struct TextAttr TOPAZ60 = {"topaz.font", TOPAZ_SIXTY,
  1817. X    FS_NORMAL, FPF_ROMFONT};
  1818. X
  1819. Xstatic struct IntuiText BodyText2 = {-1, -1,    /* pen numbers */
  1820. X                             0,             /* draw mode */
  1821. X                             9,14,          /* starting offsets */
  1822. X                             &TOPAZ60,      /* text attribute pointer */
  1823. X                             "for CLI use only!",
  1824. X                             NULL };
  1825. X
  1826. Xstatic struct IntuiText BodyText1 = {-1,-1,      /* pen numbers */
  1827. X                             0,             /* draw mode */
  1828. X                             29,4,          /* starting offsets */
  1829. X                             &TOPAZ60,      /* text attribute pointer */
  1830. X                             "GIFMachine is",
  1831. X                             &BodyText2 };
  1832. X
  1833. Xstatic struct IntuiText ContinueText = {-1,-1,  /* pen numbers */
  1834. X                             0,             /* draw mode */
  1835. X                             4,4,           /* starting offsets */
  1836. X                             &TOPAZ60,      /* text attribute pointer */
  1837. X                             "CONTINUE",
  1838. X                             NULL };
  1839. X
  1840. Xvoid WarnMustUseCLI(void)
  1841. X{
  1842. X    AutoRequest(NULL,&BodyText1,NULL,&ContinueText,0,0,220,64);
  1843. X}
  1844. END_OF_FILE
  1845. if test 1457 -ne `wc -c <'warncli.c'`; then
  1846.     echo shar: \"'warncli.c'\" unpacked with wrong size!
  1847. fi
  1848. # end of 'warncli.c'
  1849. fi
  1850. if test -f 'writeiff.c' -a "${1}" != "-c" ; then 
  1851.   echo shar: Will not clobber existing file \"'writeiff.c'\"
  1852. else
  1853. echo shar: Extracting \"'writeiff.c'\" \(6554 characters\)
  1854. sed "s/^X//" >'writeiff.c' <<'END_OF_FILE'
  1855. X/* Copyright 1990 by Christopher A. Wichura.
  1856. X   See file GIFMachine.doc for full description of rights.
  1857. X*/
  1858. X
  1859. X#include "GIFMachine.h"
  1860. X#include <iff/ILBM.h>
  1861. X
  1862. Xextern struct GIFdescriptor gdesc;
  1863. XEXTERNBITPLANE;
  1864. X
  1865. Xextern char *AbortMsg;
  1866. X
  1867. Xextern UWORD *SHAMmem;
  1868. XBYTE *PlaneBuf;
  1869. X
  1870. XBOOL Laced;
  1871. X
  1872. Xstatic BPTR ofh;
  1873. X
  1874. XUBYTE *Planes[6];
  1875. X
  1876. Xstatic UBYTE CompBuf[256];
  1877. Xstatic ULONG PlanePos;
  1878. X
  1879. XBOOL WriteIFF(char *tofile)
  1880. X{
  1881. X    register int index;
  1882. X    register ULONG ChunkSize;
  1883. X    register UWORD current;
  1884. X
  1885. X    ColorRegister ColourBuf;
  1886. X
  1887. X    ULONG FormSize, BodySize, BodySizePos;
  1888. X
  1889. X    Printf("...Writing IFF file.");
  1890. X
  1891. X    if (!(ofh = ArpOpen(tofile, MODE_NEWFILE))) {
  1892. X        Printf("\n......Error %ld trying to create %s.", IoErr(), tofile);
  1893. X        return TRUE;
  1894. X    }
  1895. X
  1896. X    gdesc.gd_Width &= ~1L;    /* make sure width is even */
  1897. X
  1898. X    if (PutLong(FORM) || PutLong(0L) || PutLong(ID_ILBM))
  1899. X        return TRUE;
  1900. X
  1901. X#define WRITTENBY "Written by GIFMachine on "
  1902. X
  1903. X    ChunkSize = strlen(WRITTENBY) + LEN_DATSTRING;
  1904. X    if (IS_ODD(ChunkSize))
  1905. X        ChunkSize++;
  1906. X
  1907. X    if (PutLong(MakeID('A','N','N','O')) || PutLong(ChunkSize))
  1908. X        return TRUE;
  1909. X
  1910. X    if (Write(ofh, WRITTENBY, strlen(WRITTENBY)) != strlen(WRITTENBY)) {
  1911. X        Printf("\n......Error %ld during write.\n", IoErr());
  1912. X        return TRUE;
  1913. X    }
  1914. X
  1915. X    {
  1916. X        struct DateTime dat;
  1917. X        char Date[LEN_DATSTRING];
  1918. X
  1919. X        DateStamp((LONG *)&dat.dat_Stamp);
  1920. X        dat.dat_Format = FORMAT_DOS;
  1921. X        dat.dat_Flags = 0;
  1922. X        dat.dat_StrDay = NULL;
  1923. X        dat.dat_StrDate = Date;
  1924. X        dat.dat_StrTime = NULL;
  1925. X
  1926. X        memset(Date, 0, LEN_DATSTRING);
  1927. X        StamptoStr(&dat);
  1928. X
  1929. X        if (Write(ofh, Date, LEN_DATSTRING) != LEN_DATSTRING) {
  1930. X            Printf("\n......Error %ld during write.\n", IoErr());
  1931. X            return TRUE;
  1932. X        }
  1933. X    }
  1934. X
  1935. X    if (IS_ODD(Seek(ofh, 0, OFFSET_CURRENT)))
  1936. X        PutChar(0);
  1937. X
  1938. X    if (PutLong(ID_BMHD) || PutLong(sizeof(BitMapHeader)))
  1939. X        return TRUE;
  1940. X
  1941. X    if (PutWord(gdesc.gd_Width) || PutWord(gdesc.gd_Height) ||
  1942. X        PutLong(0L) /* x,y pos both zero */ || PutChar(6) ||
  1943. X        PutChar(mskNone) || PutChar(cmpByteRun1) || PutChar(0) ||
  1944. X        PutWord(0) /* background is transparent colour */ ||
  1945. X        PutChar((UBYTE)(Laced ? x320x400Aspect : x320x200Aspect)) ||
  1946. X        PutChar((UBYTE)(Laced ? y320x400Aspect : y320x200Aspect)) ||
  1947. X        PutWord(320) || PutWord((UWORD)(Laced ? 400 : 200)))
  1948. X        return TRUE;
  1949. X
  1950. X    if (PutLong(ID_CAMG) || PutLong(4) ||
  1951. X        PutLong(Laced ? 0x804 : 0x800))
  1952. X        return TRUE;
  1953. X
  1954. X    if (PutLong(ID_CMAP) || PutLong(16 * 3))
  1955. X        return TRUE;
  1956. X
  1957. X    for (index = 0; index < 16; index++) {
  1958. X        current = SHAMmem[index];
  1959. X
  1960. X        ColourBuf.red   = (current >> 4) & 0xF0;
  1961. X        ColourBuf.green = current & 0xF0;
  1962. X        ColourBuf.blue  = (current & 15) << 4;
  1963. X
  1964. X        if (Write(ofh, (char *)&ColourBuf, sizeofColorRegister) !=
  1965. X            sizeofColorRegister) {
  1966. X            Printf("\n......Error %ld during write.\n", IoErr());
  1967. X                return TRUE;
  1968. X        }
  1969. X    }
  1970. X
  1971. X    ChunkSize = (Laced ? gdesc.gd_Height / 2 : gdesc.gd_Height) * 16 * sizeof(UWORD);
  1972. X
  1973. X    if (PutLong(MakeID('S','H','A','M')) || PutLong(ChunkSize + 2) || PutWord(0))
  1974. X        return TRUE;
  1975. X
  1976. X    if (Write(ofh, (char *)SHAMmem, ChunkSize) != ChunkSize) {
  1977. X        Printf("\n......Error %ld during write.\n", IoErr());
  1978. X        return TRUE;
  1979. X    }
  1980. X
  1981. X    if (PutLong(ID_BODY))
  1982. X        return TRUE;
  1983. X
  1984. X    BodySizePos = Seek(ofh, 0, OFFSET_CURRENT);
  1985. X    if (PutLong(0L))
  1986. X        return TRUE;
  1987. X
  1988. X    /* now we actually write the body chunk out */
  1989. X    {
  1990. X        register int plane;
  1991. X        register int col;
  1992. X        register UWORD x;
  1993. X        register UWORD y;
  1994. X        UBYTE PlaneMask, ColMask;
  1995. X        UWORD Cols;
  1996. X
  1997. X        Printf("\n......Line ");
  1998. X
  1999. X        Cols = (gdesc.gd_Width + 7) / 8;
  2000. X        if (IS_ODD(Cols))
  2001. X            Cols++;
  2002. X
  2003. X        for (y = 0; y < gdesc.gd_Height; y++) {
  2004. X            Printf("%5ld", y);
  2005. X
  2006. X            if (CheckAbort(NULL)) {
  2007. X                Printf("\n%s\n", AbortMsg);
  2008. X                XCEXIT(ABORTEXITVAL);
  2009. X            }
  2010. X
  2011. X            col = 0;
  2012. X            ColMask = 1L << 7;
  2013. X
  2014. X            for (x = 0; x < gdesc.gd_Width; x++) {
  2015. X                current = GetValue(x, y);
  2016. X
  2017. X                PlaneMask = 1;
  2018. X                for (plane = 0; plane < 6; plane++) {
  2019. X                    if (current & PlaneMask)
  2020. X                        Planes[plane][col] |= ColMask;
  2021. X
  2022. X                    PlaneMask <<= 1;
  2023. X                }
  2024. X
  2025. X                if (ColMask == 1) {
  2026. X                    ColMask = 1L << 7;
  2027. X                    col++;
  2028. X                } else
  2029. X                    ColMask >>= 1;
  2030. X            }
  2031. X
  2032. X            /* now we need to compress the scan line */
  2033. X
  2034. X            {
  2035. X                register BOOL state;
  2036. X                register char c;
  2037. X                register char lastc;
  2038. X                register UWORD nbuf;
  2039. X                register UWORD rstart;
  2040. X
  2041. X                for (plane = 0; plane < 6; plane++) {
  2042. X
  2043. X                    CompBuf[0] = lastc = c = Planes[plane][0];
  2044. X
  2045. X                    state = FALSE;
  2046. X                    PlanePos = rstart = 0;
  2047. X                    nbuf = col = 1;
  2048. X
  2049. X                    while (col < Cols) {
  2050. X                        CompBuf[nbuf++] = c = Planes[plane][col++];
  2051. X
  2052. X                        switch (state) {
  2053. X                            case FALSE:
  2054. X                            if (nbuf > 128) {
  2055. X                                OutDump(nbuf - 1);
  2056. X                                CompBuf[0] = c;
  2057. X                                nbuf = 1;
  2058. X                                rstart = 0;
  2059. X                                break;
  2060. X                            }
  2061. X
  2062. X                            if (c == lastc) {
  2063. X                                if (nbuf - rstart >= 3) {
  2064. X                                    if (rstart > 0)
  2065. X                                        OutDump(rstart);
  2066. X                                    state = TRUE;
  2067. X                                } else if (rstart == 0)
  2068. X                                    state = TRUE;
  2069. X                            } else
  2070. X                                rstart = nbuf - 1;
  2071. X
  2072. X                            break;
  2073. X
  2074. X                            case TRUE:
  2075. X                            if ((c != lastc) || (nbuf - rstart > 128)) {
  2076. X                                OutRun(nbuf - 1 - rstart, lastc);
  2077. X                                CompBuf[0] = c;
  2078. X                                nbuf = 1;
  2079. X                                rstart = 0;
  2080. X                                state = FALSE;
  2081. X                            }
  2082. X
  2083. X                            break;
  2084. X                        }
  2085. X
  2086. X                        lastc = c;
  2087. X                    }
  2088. X
  2089. X                    switch (state) {
  2090. X                        case FALSE:
  2091. X                        OutDump(nbuf);
  2092. X                        break;
  2093. X
  2094. X                        case TRUE:
  2095. X                        OutRun(nbuf - rstart, lastc);
  2096. X                        break;
  2097. X                    }
  2098. X
  2099. X                    /* now write the compressed plane out */
  2100. X                    if (Write(ofh, (char *)PlaneBuf, PlanePos) != PlanePos) {
  2101. X                        Printf("\n......Error %ld during write.\n", IoErr());
  2102. X                        return TRUE;
  2103. X                    }
  2104. X
  2105. X                    memset((char *)Planes[plane], 0, Cols);
  2106. X                }        
  2107. X            }
  2108. X
  2109. X            Printf("\x9B" "5D");
  2110. X        }
  2111. X
  2112. X    }
  2113. X
  2114. X    /* finished writing the body so pad it if needed and then fix a
  2115. X       a couple chunk sizes and we are done! */
  2116. X
  2117. X    if (IS_ODD(Seek(ofh, 0, OFFSET_CURRENT)))
  2118. X        if (PutChar(0))
  2119. X            return TRUE;
  2120. X
  2121. X    BodySize = Seek(ofh, 0, OFFSET_CURRENT) - BodySizePos - 4;
  2122. X    FormSize = Seek(ofh, 0, OFFSET_CURRENT) - 8;
  2123. X
  2124. X    Seek(ofh, 4, OFFSET_BEGINNING);
  2125. X    if (PutLong(FormSize))
  2126. X        return TRUE;
  2127. X
  2128. X    Seek(ofh, BodySizePos, OFFSET_BEGINNING);
  2129. X    PutLong(BodySize);
  2130. X
  2131. X    Puts("\x9B" "5D\x9BKWritten.");
  2132. X
  2133. X    return TRUE;
  2134. X}
  2135. X
  2136. Xvoid OutDump(int nn)
  2137. X{
  2138. X    register int index;
  2139. X
  2140. X    PlaneBuf[PlanePos++] = nn - 1;
  2141. X
  2142. X    for (index = 0; index < nn; index++)
  2143. X        PlaneBuf[PlanePos++] = CompBuf[index];
  2144. X}
  2145. X
  2146. Xvoid OutRun(int nn, int cc)
  2147. X{
  2148. X    PlaneBuf[PlanePos++] = -(nn - 1);
  2149. X    PlaneBuf[PlanePos++] = cc;
  2150. X}
  2151. X
  2152. XBOOL PutLong(ULONG l)
  2153. X{
  2154. X    if (PutWord((UWORD)(l >> 16)))
  2155. X        return TRUE;
  2156. X    return PutWord((UWORD)l);
  2157. X}
  2158. X
  2159. XBOOL PutWord(UWORD w)
  2160. X{
  2161. X    if (PutChar((UBYTE)(w >> 8)))
  2162. X        return TRUE;
  2163. X    return PutChar((UBYTE)w);
  2164. X}
  2165. X
  2166. XBOOL PutChar(UBYTE b)
  2167. X{
  2168. X    char buf[1];
  2169. X
  2170. X    buf[0] = b;
  2171. X    if (Write(ofh, buf, 1) != 1) {
  2172. X        Printf("\n......Error %ld during write.\n", IoErr());
  2173. X        return TRUE;
  2174. X    }
  2175. X}
  2176. END_OF_FILE
  2177. if test 6554 -ne `wc -c <'writeiff.c'`; then
  2178.     echo shar: \"'writeiff.c'\" unpacked with wrong size!
  2179. fi
  2180. # end of 'writeiff.c'
  2181. fi
  2182. if test -f 'xcomp.c' -a "${1}" != "-c" ; then 
  2183.   echo shar: Will not clobber existing file \"'xcomp.c'\"
  2184. else
  2185. echo shar: Extracting \"'xcomp.c'\" \(2470 characters\)
  2186. sed "s/^X//" >'xcomp.c' <<'END_OF_FILE'
  2187. X/* Copyright 1990 by Christopher A. Wichura.
  2188. X   See file GIFMachine.doc for full description of rights.
  2189. X*/
  2190. X
  2191. X/* This function will take the gif screen we have read in and scale it to
  2192. X   one half of its previous X size.
  2193. X
  2194. X   What we do here is just a step above skipping every other pixel (like
  2195. X   most routines I have seen do).  While we still put emphasis on the
  2196. X   even pixels, we at least take account of the odds next to them by
  2197. X   using a weighted average.
  2198. X
  2199. X   This method is by no means the best way to do this.  If anyone wants
  2200. X   to build a smarter one I would be very interested in seeing it.
  2201. X*/
  2202. X
  2203. X#include "GIFMachine.h"
  2204. X
  2205. Xextern struct GIFdescriptor gdesc;
  2206. XEXTERNBITPLANE;
  2207. X
  2208. Xextern char *AbortMsg;
  2209. X
  2210. Xextern UWORD MasterColourTable[MAXCOLOURS];
  2211. Xextern UWORD TotalColours;
  2212. X
  2213. Xvoid DoXComp(void)
  2214. X{
  2215. X    register UWORD x1;
  2216. X    register UWORD x2;
  2217. X    register UWORD y;
  2218. X    register UWORD ColourIndex;
  2219. X    register UWORD num;
  2220. X    UBYTE ColBuf[3];
  2221. X    UWORD OldNumColours;
  2222. X    UWORD NewWidth;
  2223. X
  2224. X    NewWidth = gdesc.gd_Width >> 1;
  2225. X    if (NewWidth & 1)
  2226. X        NewWidth++;
  2227. X
  2228. X    Printf("...Compressing width to %ld.\n......Line ", NewWidth);
  2229. X    OldNumColours = TotalColours;
  2230. X
  2231. X        for (y = 0; y < gdesc.gd_Height; y++) {
  2232. X        Printf("%5ld", y);
  2233. X
  2234. X        for (x1 = x2 = 0; x2 < gdesc.gd_Width; x1++, x2 += 2) {
  2235. X            num = 4;
  2236. X            ColourIndex = GetValue(x2, y);
  2237. X
  2238. X            ColBuf[0] = GetRed(ColourIndex) * 4;
  2239. X            ColBuf[1] = GetGreen(ColourIndex) * 4;
  2240. X            ColBuf[2] = GetBlue(ColourIndex) * 4;
  2241. X
  2242. X            if (x2 > 1) {
  2243. X                num += 2;
  2244. X                ColourIndex = GetValue((UWORD)(x2 - 1), y);
  2245. X
  2246. X                ColBuf[0] += GetRed(ColourIndex) * 2;
  2247. X                ColBuf[1] += GetGreen(ColourIndex) * 2;
  2248. X                ColBuf[2] += GetBlue(ColourIndex) * 2;
  2249. X            }
  2250. X
  2251. X            if (x2 + 1 < gdesc.gd_Width) {
  2252. X                num += 2;
  2253. X                ColourIndex = GetValue((UWORD)(x2 + 1), y);
  2254. X
  2255. X                ColBuf[0] += GetRed(ColourIndex) * 2;
  2256. X                ColBuf[1] += GetGreen(ColourIndex) * 2;
  2257. X                ColBuf[2] += GetBlue(ColourIndex) * 2;
  2258. X            }
  2259. X
  2260. X            ColBuf[0] = ((ColBuf[0] + num / 2) / num) << 4;
  2261. X            ColBuf[1] = ((ColBuf[1] + num / 2) / num) << 4;
  2262. X            ColBuf[2] = ((ColBuf[2] + num / 2) / num) << 4;
  2263. X
  2264. X            ColourIndex = AddColour(ColBuf);
  2265. X
  2266. X            PutValue(x1, y, ColourIndex);
  2267. X        }
  2268. X
  2269. X        PutValue(x1, y, gdesc.gd_BackGround);
  2270. X
  2271. X        if (CheckAbort(NULL)) {
  2272. X            Printf("\n%s\n", AbortMsg);
  2273. X            XCEXIT(ABORTEXITVAL);
  2274. X        }
  2275. X
  2276. X        Printf("\x9B" "5D");
  2277. X    }
  2278. X
  2279. X    Puts("\x9B" "5DCompressed.");
  2280. X
  2281. X    if (TotalColours > OldNumColours)
  2282. X        Printf("......Total unique colours increased by %ld to %ld.\n",
  2283. X            TotalColours - OldNumColours, TotalColours);
  2284. X
  2285. X    gdesc.gd_Width = NewWidth;
  2286. X}
  2287. END_OF_FILE
  2288. if test 2470 -ne `wc -c <'xcomp.c'`; then
  2289.     echo shar: \"'xcomp.c'\" unpacked with wrong size!
  2290. fi
  2291. # end of 'xcomp.c'
  2292. fi
  2293. echo shar: End of archive 1 \(of 2\).
  2294. cp /dev/null ark1isdone
  2295. MISSING=""
  2296. for I in 1 2 ; do
  2297.     if test ! -f ark${I}isdone ; then
  2298.     MISSING="${MISSING} ${I}"
  2299.     fi
  2300. done
  2301. if test "${MISSING}" = "" ; then
  2302.     echo You have unpacked both archives.
  2303.     rm -f ark[1-9]isdone
  2304. else
  2305.     echo You still need to unpack the following archives:
  2306.     echo "        " ${MISSING}
  2307. fi
  2308. ##  End of shell archive.
  2309. exit 0
  2310. -- 
  2311. Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
  2312. Mail comments to the moderator at <amiga-request@uunet.uu.net>.
  2313. Post requests for sources, and general discussion to comp.sys.amiga.
  2314.